package com.traveldream.testing;

import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;

import com.traveldream.entities.Excursion;
import com.traveldream.entities.Product;
import com.traveldream.entity_managers.ProductManager;

@ManagedBean(name="product_manager_test")
@SessionScoped
public class ProductManagerTest implements TestingTravelDream {
	
	@EJB
	private ProductManager pm;
	
	@ManagedProperty(value="#{test_bean}")
	private TestBean testBean;
	
	private String log;
	private StringBuilder logSb;
	
	// i test avvengono su variabili Escursion 
	// per le entity Flight e Hotel i metodi sono duali

	@Override
	public void runTests() {
		logSb=new StringBuilder(300);
		logSb.append("******** TESTING DEL SESSION BEAN: PRODUCT MANAGER *******");logSb.append(System.lineSeparator());
		logSb.append("***** INIZIO TESTING *****");	logSb.append(System.lineSeparator());
		addTest();
		logSb.append(System.lineSeparator());
		deleteTest();
		logSb.append(System.lineSeparator());
		addDeleteTest();
		logSb.append(System.lineSeparator());
		updateTest();
		logSb.append(System.lineSeparator());
		findByParametersTest();
		this.log=logSb.toString();
		System.out.print(this.log);
		testBean.setProd(true); testBean.setPack(false); testBean.setBook(false);	testBean.setInv(false);
	}

	public TestBean getTestBean() {
		return testBean;
	}

	public void setTestBean(TestBean testBean) {
		this.testBean = testBean;
	}

	@Override
	public void addTest() {
		logSb.append("*** ADD TEST PRODUCT MANAGER ***");logSb.append(System.lineSeparator());
		List<Excursion> initialState=pm.findAllExcursions();
		logSb.append("> INITIAL STATE: {");
		for( Excursion e: initialState )
			logSb.append("   "+e.getProductId());
		logSb.append("   }");logSb.append(System.lineSeparator());
		Product p=new Product();
		Excursion nuova=new Excursion();	nuova.setProduct(p);	
		logSb.append("> NEW PRODUCT CREATED");logSb.append(System.lineSeparator());	
		logSb.append("> NEW PRODUCT ADDED id = "+pm.create(nuova).getProductId());logSb.append(System.lineSeparator());
		List<Excursion> finalState=pm.findAllExcursions();
		logSb.append("> FINAL STATE: {");
		for( Excursion e: finalState )
			logSb.append("   "+e.getProductId());
		logSb.append("   }");logSb.append(System.lineSeparator());
		initialState.add(nuova);
		Comparator<Excursion> comp=new Comparator<Excursion>() {
			public int compare(Excursion e1, Excursion e2) { 
				return e1.getProductId()-e2.getProductId();
			}
		};
		Collections.sort(initialState,comp);
		Collections.sort(finalState,comp);
		
		if( initialState.equals(finalState) )
			logSb.append(" *** TEST PERFORMED SUCCESSFULLY ***");
		else
			logSb.append(" *** TEST FAILURE ***\n ");
		logSb.append(System.lineSeparator());
		logSb.append(" *** END ADD TEST ***");logSb.append(System.lineSeparator());
	}

	@Override
	public void deleteTest() {
		logSb.append("*** DELETE TEST PRODUCT MANAGER ***");	logSb.append(System.lineSeparator());
		List<Excursion> initialState=pm.findAllExcursions();
		logSb.append("> INITIAL STATE: {");
		for( Excursion e: initialState )
			logSb.append("   "+e.getProductId());
		logSb.append("   }");logSb.append(System.lineSeparator());
		if( initialState.size()==0 )  { 
			logSb.append("> !!! IMPOSSIBLE RUN THE TEST: NO ELEMENTS FOUND ");logSb.append(System.lineSeparator());
			return;
		}
		int id=initialState.get(0).getProductId();
		pm.delete(id);
		initialState.remove(0);
		logSb.append("> PRODUCT DELETED: id = "+id);logSb.append(System.lineSeparator());
		List<Excursion> finalState=pm.findAllExcursions();
		logSb.append("> FINAL STATE: {");
		for( Excursion e: finalState )
			logSb.append("   "+e.getProductId());
		logSb.append("   }");logSb.append(System.lineSeparator());
		Comparator<Excursion> comp=new Comparator<Excursion>() {
			public int compare(Excursion e1, Excursion e2) { 
				return e1.getProductId()-e2.getProductId();
			}
		};
		Collections.sort(initialState,comp);
		Collections.sort(finalState,comp);
		
		if( initialState.equals(finalState) )
			logSb.append(" *** TEST PERFORMED SUCCESSFULLY *** ");
		else
			logSb.append(" *** TEST FAILURE *** ");
		logSb.append(System.lineSeparator());
		logSb.append(" *** END DELETE TEST ***");	logSb.append(System.lineSeparator());
	}

	@Override
	public void addDeleteTest() {
		logSb.append("*** ADD-DELETE TEST PRODUCT MANAGER ***");logSb.append(System.lineSeparator());
		//visualize initial state
		List<Excursion> initialState=pm.findAllExcursions();
		logSb.append("> INITIAL STATE: {");
		for( Excursion e: initialState )
			logSb.append("   "+e.getProductId());
		logSb.append("   }");	logSb.append(System.lineSeparator());
		// add new excursion
		Product p=new Product();
		Excursion nuova=new Excursion();	nuova.setProduct(p);	
		logSb.append("> NEW PRODUCT CREATED");			logSb.append(System.lineSeparator());
		int id=pm.create(nuova).getProductId();
		logSb.append("> NEW PRODUCT ADDED id = "+id);logSb.append(System.lineSeparator());
		//visualize intermediate state
		List<Excursion> intermediateState=pm.findAllExcursions();
		logSb.append("> INTERMEDIATE STATE: {");
		for( Excursion e: intermediateState )
			logSb.append("   "+e.getProductId());
		logSb.append("   }");
		logSb.append(System.lineSeparator());
		//delete the same product
		pm.delete(id);
		logSb.append("> PRODUCT DELETED: id = "+id);logSb.append(System.lineSeparator());
		//visualize the final state
		List<Excursion> finalState=pm.findAllExcursions();
		logSb.append("> FINAL STATE: {");
		for( Excursion e: finalState )
			logSb.append("   "+e.getProductId());
		logSb.append("   }");
		logSb.append(System.lineSeparator());
		//sort lists
		Comparator<Excursion> comp=new Comparator<Excursion>() {
			public int compare(Excursion e1, Excursion e2) { 
				return e1.getProductId()-e2.getProductId();
			}
		};
		Collections.sort(initialState,comp);
		Collections.sort(finalState,comp);
		//check if inital and final states are equals
		if( initialState.equals(finalState) )
			logSb.append(" *** TEST PERFORMED SUCCESSFULLY *** ");
		else
			logSb.append(" *** TEST FAILURE *** ");
		logSb.append(System.lineSeparator());
		logSb.append(" *** END ADD-DELETE TEST ***");	logSb.append(System.lineSeparator());
	}

	@Override
	public void updateTest() {
		logSb.append("*** UPDATE TEST PRODUCT MANAGER ***");logSb.append(System.lineSeparator());
		//visualize initial state
		List<Excursion> initialState=pm.findAllExcursions();
		logSb.append("> INITIAL STATE: {");
		for( Excursion e: initialState )
			logSb.append("   "+e.getProductId());
		logSb.append("   }");
		logSb.append(System.lineSeparator());
		//create new excursion with name = before
		Product p=new Product();
		Excursion e=new Excursion();
		e.setProduct(p);
		e.setName("before"); e.setDescription("product created for testing");
		Excursion before=pm.create(e);
		int id=before.getProductId();
		logSb.append("> PRODUCT ADDED: id = "+id+", name = "+before.getName()+", description = "+before.getDescription());logSb.append(System.lineSeparator());
		//modify the object and update it
		before.setName("after");
		before.setDescription("product modified for testing");
		pm.update(before);
		logSb.append("> PRODUCT UPDATED ");logSb.append(System.lineSeparator());
		Excursion after=pm.findExcursion(id);
		logSb.append("> PRODUCT TAKEN FROM DB");logSb.append(System.lineSeparator());
		logSb.append("> PRODUCT UPDATED: id = "+id+", name = "+after.getName()+", description = "+after.getDescription());logSb.append(System.lineSeparator());
		if( before.getName().equals(after.getName()) && before.getDescription().equals(after.getDescription()) )
			logSb.append(" *** TEST PERFORMED SUCCESSFULLY");
		else
			logSb.append(" *** TEST FAILURE *** ");
		logSb.append(System.lineSeparator());
		logSb.append(" *** END UPDATE TEST ***");	logSb.append(System.lineSeparator());
	}

	@SuppressWarnings("deprecation")
	@Override
	public void findByParametersTest() {
		logSb.append("*** FIND TEST PRODUCT MANAGER ***");logSb.append(System.lineSeparator());
		//visualize initial state
		List<Excursion> initialState=pm.findAllExcursions();
		logSb.append("> INITIAL STATE: {");
		for( Excursion e: initialState )
			logSb.append("   "+e.getProductId());
		logSb.append("   }");logSb.append(System.lineSeparator());
		//create new excursion with name = new, date = 30/01/2014
		Product p=new Product();
		Excursion e=new Excursion();
		e.setProduct(p);
		GregorianCalendar in=new GregorianCalendar(2014,GregorianCalendar.JANUARY,30);
		e.setName("new"); e.setDescription("product created for testing");
		Date nuovaDate=in.getTime();
		e.setDate(nuovaDate);
		Excursion nuova=pm.create(e);
		int id=nuova.getProductId();
		logSb.append("> PRODUCT ADDED: id = "+id+", name = "+nuova.getName()+", description = "+nuova.getDescription()+", date = "+in.getTime().toLocaleString());
		logSb.append(System.lineSeparator());
		//find the object
		GregorianCalendar param1=new GregorianCalendar(2014,GregorianCalendar.JANUARY,28);
		GregorianCalendar param2=new GregorianCalendar(2014,GregorianCalendar.FEBRUARY,02);
		List<Excursion> query=pm.findExcursionByDates(param1.getTime(),param2.getTime());
		logSb.append("> QUERY EXECUTED: find excursions between "+param1.getTime().toLocaleString()+" and "+param2.getTime().toLocaleString());
		logSb.append(System.lineSeparator());
		//visualize results
		boolean found=false;
		logSb.append("> QUERY RESULTS: {");
			for( Excursion x: query ) {
				if( x.getProductId()==id ) found=true;
				logSb.append("   "+x.getProductId());
			}
			logSb.append("   }");
			logSb.append(System.lineSeparator());
		if( found )
			logSb.append(" *** TEST PERFORMED SUCCESSFULLY");
		else
			logSb.append(" *** TEST FAILURE *** ");
		logSb.append(System.lineSeparator());
		logSb.append(" *** END FIND TEST ***");	logSb.append(System.lineSeparator());
	}
	
	public String getLog() {
		return log;
	}

	public void setLog(String log) {
		this.log = log;
	}
}
